//addr ==  UART_ADDR  --> uart
//addr ==  LED_ADDR   --> led ( w_post_code )
//clock  150m
module spi2uart(/*autoarg*/
   // Outputs
   tx_en, tx_data, w_post_code, response_wait, data_to_ip,
   cycle_to_ip, tag_to_ip, length_to_ip, code_to_ip, specific_to_ip,
   addr_to_ip, response_defer, status_avail,
   // Inputs
   clk, rst, tx_rdy, rx_vld, rx_data, rx_err, command_valid, command,
   error_en, error_data, data_req, data_valid, data_from_ip,
   addr_valid, address, hdr_valid, cycle, tag, length, message_valid,
   message_code, message_specific
   );

parameter  UART_ADDR = 16'h03f8 ;
parameter  LED_ADDR  = 16'h0080 ;

parameter  UART_FIFO_DEPTH =  6            ;
parameter  UART_FIFO_MAX   = (1<<UART_FIFO_DEPTH) -2  ;

parameter  UART_IDLE_STATE  = 2'd0 ;
parameter  UART_WFIFO_STATE = 2'd1 ;
parameter  LED_STATE        = 2'd2 ;

input         clk ;
input         rst ;

//to uart 
output wire         tx_en    ;
output wire  [7:0]  tx_data  ;
input               tx_rdy   ;

output      [ 7:0]   w_post_code ;

//from uart
input         rx_vld    ;
input  [7:0]  rx_data   ;
input         rx_err    ;

//common  espi 
input wire 		command_valid		;
input wire	[7:0]	command			;
input wire		error_en		;
input wire	[15:0]	error_data		;
input wire		data_req		;
input wire		data_valid		;
input wire	[7:0]	data_from_ip		;

output wire		response_wait  		; 	
output wire [7:0]	data_to_ip		;

// PERIPHERAL channel 0
output  wire [7:0]	cycle_to_ip		;
output  wire [3:0]	tag_to_ip		;
output  wire [11:0]	length_to_ip		;
output  wire [7:0]	code_to_ip		;
output  wire [31:0]	specific_to_ip		;
output  wire [63:0]	addr_to_ip		;

input wire	[2:0]	addr_valid		;
input wire	[63:0]	address			;
input wire		hdr_valid		;
input wire	[7:0]	cycle			;
input wire	[3:0]	tag			;
input wire	[11:0]	length			;
input wire		message_valid		;
input wire	[7:0]	message_code		;
input wire	[31:0]	message_specific	;

output  wire		response_defer		;
output  wire [1:0]	status_avail		;


//////////////////////////////////////////////////////////////////////////////////////////////////
//output to  espi 
assign   response_wait  	 =  'd0  ;
assign   data_to_ip		 =  'd0  ;
assign   cycle_to_ip		 =  'd0  ;
assign   tag_to_ip		 =  'd0  ;
assign   length_to_ip		 =  'd0  ;
assign   code_to_ip		 =  'd0  ;
assign   specific_to_ip		 =  'd0  ;
assign   addr_to_ip		 =  'd0  ;
assign   response_defer	         =  'd0  ;
assign   status_avail		 =  'd0  ;


reg         [ 7:0]   w_post_code ;


//////////////////////////////////////////////////////////////////////////////////////////////////
reg  [1:0]    uart_cstate;
reg  [1:0]    uart_nstate;

wire  uart_idle_st    =  (  uart_cstate==  UART_IDLE_STATE       );
wire  uart_wfifo_st   =  (  uart_cstate==  UART_WFIFO_STATE      );
wire  led_st          =  (  uart_cstate==  LED_STATE             );

always@ ( * )
begin
  uart_nstate = uart_cstate;
  case( uart_cstate )
  UART_IDLE_STATE : begin  
          if ( |addr_valid   &&  (address==UART_ADDR)    )  begin
	     uart_nstate = UART_WFIFO_STATE ;
	  end
	  else if ( |addr_valid   &&  (address==LED_ADDR)    )  begin
	     uart_nstate = LED_STATE ;
	  end
  end
  UART_WFIFO_STATE: begin
          if ( |addr_valid   &&  (address==UART_ADDR)    )  begin
	     uart_nstate = UART_WFIFO_STATE ;
	  end
	  else if ( |addr_valid   &&  (address==LED_ADDR)    )  begin
	     uart_nstate = LED_STATE ;
  	  end
	  else if ( |addr_valid )
	     uart_nstate = UART_IDLE_STATE ;  		
  end
  LED_STATE: begin
  	if ( |addr_valid   &&  (address==UART_ADDR)    )  begin
	     uart_nstate = UART_WFIFO_STATE ;
	end
	else if ( |addr_valid   &&  (address==LED_ADDR)    )  begin
	     uart_nstate = LED_STATE ;
	end
	else if ( |addr_valid) begin 
	     uart_nstate = UART_IDLE_STATE ;  			     
	end
  end
  default:  uart_nstate = UART_IDLE_STATE ;
  endcase   
end


always@ ( posedge rst  or posedge clk)
begin
  if ( rst ) begin
     uart_cstate  <=  2'd0 ;
  end
  else begin 
     uart_cstate  <=  uart_nstate ;
  end
end

////////////////////////////////////////////////////////////////////////

wire  [7:0]                 uart_fifo_out   ;
wire  [UART_FIFO_DEPTH:0]   uart_fifo_usedw ;
wire                        uart_fifo_empty ;

reg                         uart_fifo_we    ;
reg   [7:0]                 uart_fifo_din   ;

wire                        uart_fifo_re    ;

fifo #( 8 ,  UART_FIFO_DEPTH  ,  0 )  u_uart_fifo(
   // Outputs
   .fifo_out    (uart_fifo_out), 
   .fifo_usedw  (uart_fifo_usedw),
   .fifo_empty  (uart_fifo_empty),
   // Inputs
   .clk         (clk ), 
   .rst_n       (~rst), 
   .fifo_clr    (1'b0), 
   .fifo_we     (uart_fifo_we), 
   .fifo_in     (uart_fifo_din), 
   .fifo_re     (uart_fifo_re)
   );

always@ ( posedge rst  or posedge clk)
begin
  if ( rst ) begin
     uart_fifo_we  <=  2'd0 ;
  end
  else if ( uart_fifo_usedw<=UART_FIFO_MAX  )  begin 
     uart_fifo_we  <=   data_valid&&uart_wfifo_st  ;
  end
  else begin
     uart_fifo_we  <=  2'd0 ;
  end
end

always@ ( posedge rst  or posedge clk)
begin
  if ( rst ) begin
     uart_fifo_din  <=  2'd0 ;
  end
  else if (data_valid&&uart_wfifo_st  )  begin
     uart_fifo_din  <=  data_from_ip ;
  end
end

assign   uart_fifo_re = tx_rdy && (~uart_fifo_empty) ;
assign   tx_en        = tx_rdy && (~uart_fifo_empty) ;
assign   tx_data      = uart_fifo_out                ;


////////////////////////////////////////////////////////////////////////

//w_post_code


reg   led_flag  ;
always@ ( posedge rst  or posedge clk)
begin
  if ( rst ) begin
     led_flag  <=  1'd0 ;
  end
  else if (data_valid&& led_st )  begin
     led_flag  <=   ~ led_flag ;
  end
end



always@ ( posedge rst  or posedge clk)
begin
  if ( rst ) begin
     w_post_code  <=  'd0 ;
  end
  else if (data_valid&& led_st )  begin
	//if (~led_flag)    w_post_code[ 7:0]  <=  data_from_ip ;
	//else              w_post_code[15:8]  <=  data_from_ip ;
 	w_post_code[ 7:0]  <=  data_from_ip ;
  end
end

////////////////////////////////////////////////////////////////////////





endmodule

